package models

import (
	"encoding/base64"
	"encoding/json"
	"fmt"
	"gitee.com/tsingeye/FreeEhome/config"
	"gitee.com/tsingeye/FreeEhome/service/ehome/udp"
	"gitee.com/tsingeye/FreeEhome/tools"
	"gitee.com/tsingeye/FreeEhome/tools/logs"
	"gitee.com/tsingeye/FreeEhome/tools/sqlDB"
	"io/ioutil"
	"net"
	"net/http"
	"os"
	"strconv"
	"strings"
	"time"
)

//指定通道实时直播启动
func InviteStream(channelID, channelType string) (replyData map[string]interface{}) {
	replyData = map[string]interface{}{
		"errCode": config.EHomeClientBadRequest,
		"errMsg":  config.HTTPCodeMap[config.EHomeClientBadRequest],
	}

	strList := strings.Split(channelID, "_")
	if len(strList) != 2 {
		logs.BeeLogger.Warn("StreamController.InviteStream() ---> channelID=%s, channelID format error!!!", channelID)
		return
	}

	realChannelID, err := strconv.ParseInt(strList[1], 0, 64)
	if err != nil {
		logs.BeeLogger.Warn("StreamController.InviteStream() ---> channelID=%s, channelID format error!!!", channelID)
		return
	}

	var channelData sqlDB.ChannelTable
	if err := sqlDB.First(&channelData, "channelID = ?", channelID); err != nil {
		logs.BeeLogger.Error("StreamController.InviteStream() ---> channelID=%s, sqlDB.First(&sqlDB.ChannelTable{}) error:%s", channelID, err)

		replyData = map[string]interface{}{
			"errCode": config.EHomeChannelIDNotFound,
			"errMsg":  config.HTTPCodeMap[config.EHomeChannelIDNotFound],
		}
		return
	}

	switch channelType {
	case "MAIN", "SUB", "THIRD":
	default:
		//默认使用子码流
		channelType = "SUB"
	}

	return udp.InviteStream(channelData.DeviceID, realChannelID, channelType)
}

//获取快照
func GetSnap(channelID string, saveSnaps bool) (replyData map[string]interface{}) {
	replyData = InviteStream(channelID, "SUB")

	if replyData["errCode"].(int64) == 200 {
		requestURL := tools.StringsJoin(config.ZLMGetSnapAddr, "&url=", replyData["urlMap"].(map[string]string)["rtmp"])
		return zlmGetSnap(channelID, requestURL, saveSnaps)
	}

	return
}

//解析请求快照图片返回结果
type responseGetSnap struct {
	Code int64  `json:"code"`
	Msg  string `json:"msg"`
}

//向ZLM请求快照图片
func zlmGetSnap(channelID, requestURL string, saveSnaps bool) (replyData map[string]interface{}) {
	replyData = map[string]interface{}{
		"errCode": config.EHomeGetSnapError,
		"errMsg":  config.HTTPCodeMap[config.EHomeGetSnapError],
	}

	client := &http.Client{
		Transport: &http.Transport{
			Dial: func(network, addr string) (net.Conn, error) {
				conn, err := net.DialTimeout(network, addr, time.Second*time.Duration(config.WaitZLMReplyTime)) //设置建立连接超时
				if err != nil {
					return nil, err
				}
				conn.SetDeadline(time.Now().Add(time.Second * time.Duration(config.WaitZLMReplyTime))) //设置发送接受数据超时
				return conn, nil
			},
			ResponseHeaderTimeout: time.Second * time.Duration(config.WaitZLMReplyTime),
		},
	}

	request, err := http.NewRequest("GET", requestURL, nil)
	if err != nil {
		logs.BeeLogger.Error("zlmGetSnap() ---> http.NewRequest() error:%s", err)
		return
	}

	response, err := client.Do(request)
	if err != nil {
		logs.BeeLogger.Error("zlmGetSnap() ---> client.Do() error:%s", err)
		return
	}

	defer response.Body.Close()

	responseBody, err := ioutil.ReadAll(response.Body)
	if err != nil {
		logs.BeeLogger.Error("zlmGetSnap() ---> ioutil.ReadAll() error:%s", err)
		return
	}

	fmt.Println("打印Header内容：", response.Header.Get("Content-Type"))
	contentType := response.Header.Get("Content-Type")
	switch strings.HasPrefix(contentType, "image/") {
	case true:
		//Content-Type: image/jpeg
		//快照截图获取成功
		if saveSnaps {
			filePath := tools.StringsJoin(tools.GetAbsPath(), "image/", channelID, "/", time.Now().Format("20060102"))
			fileName := tools.StringsJoin(time.Now().Format("20060102150405"), ".", contentType[6:])
			fileSave(filePath, fileName, responseBody)
		}
		replyData = map[string]interface{}{
			"errCode":   config.EHomeSuccessOK,
			"errMsg":    config.HTTPCodeMap[config.EHomeSuccessOK],
			"snapsData": base64.StdEncoding.EncodeToString(responseBody),
		}
		return
	default:
		//Content-Type: application/json; charset=gb2312
		//快照截图获取失败
		//{
		//	"code" : -300,
		//	"msg" : "������������:\"secret\""
		//}
		logs.BeeLogger.Error("zlmGetSnap() ---> responseBody=%s, getSnap error!!!", responseBody)

		var responseData responseGetSnap
		if err := json.Unmarshal(responseBody, &responseData); err != nil {
			logs.BeeLogger.Error("zlmGetSnap() ---> responseBody=%s, json.Unmarshal() error:%s", responseBody, err)
			return
		}

		replyData = map[string]interface{}{
			"errCode": responseData.Code,
			"errMsg":  responseData.Msg,
		}
		return
	}

	return
}

//保存图片到本地
func fileSave(filePath, fileName string, fileData []byte) {
	//创建保存快照截图的文件路径，格式形如：image/560796072_1/20210408/xxx.jpeg，其中文件路径是：image/560796072_1/20210408/
	if err := os.MkdirAll(filePath, os.ModePerm); err != nil {
		logs.BeeLogger.Error("fileSave() ---> filePath=%s, fileName=%s, os.MkdirAll() error:%s", filePath, fileName, err)
	}

	file, err := os.Create(tools.StringsJoin(filePath, "/", fileName))
	defer file.Close()
	if err != nil {
		logs.BeeLogger.Error("fileSave() ---> filePath=%s, fileName=%s, os.Create() error: %s", filePath, fileName, err)
		return
	}

	_, err = file.Write(fileData)
	if err != nil {
		logs.BeeLogger.Error("fileSave() ---> filePath=%s, fileName=%s, file.Write() error: %s", filePath, fileName, err)
		return
	}

	fmt.Println("图片保存成功")
}

//定时进行实时直播快照截图
func TimedScreenshot() {
	timeTicker := time.NewTicker(time.Duration(config.TimedScreenshotPeriod) * time.Minute)
	defer timeTicker.Stop()
	for {
		select {
		case <-timeTicker.C:
			if config.OpenTimedScreenshot {
				channelList := make([]sqlDB.ChannelTable, 0)
				if err := sqlDB.Find(&channelList); err != nil {
					logs.BeeLogger.Error("TimedScreenshot() ---> sqlDB.Find(&sqlDB.ChannelTable{}) error:%s", err)
					continue
				}

				for _, channelData := range channelList {
					go GetSnap(channelData.ChannelID, true)
				}
			}
		}
	}
}
